use serde::{Serialize, Deserialize};
use std::collections::HashMap;
use std::sync::Arc;
use tokio::sync::{Mutex, broadcast};
use tracing::{info, error, debug, warn};
use thiserror::Error;
use chrono::{DateTime, Utc};
use uuid::Uuid;
use std::process::Command;
use tokio::process::Command as TokioCommand;
use which::which;

use super::{DeviceInfo, DeviceStatus, PerformanceMetrics, SystemInfo, Platform, ConnectionType};

#[derive(Error, Debug, Clone)]
pub enum AdbError {
    #[error("Connection error: {0}")]
    Connection(String),
    #[error("Device not found: {0}")]
    DeviceNotFound(String),
    #[error("Command execution failed: {0}")]
    CommandFailed(String),
    #[error("Parse error: {0}")]
    ParseError(String),
    #[error("IO error: {0}")]
    IoError(String),
    #[error("ADB not found in PATH")]
    AdbNotFound,
    #[error("ADB server not running: {0}")]
    ServerNotRunning(String),
}

impl From<std::io::Error> for AdbError {
    fn from(err: std::io::Error) -> Self {
        AdbError::IoError(err.to_string())
    }
}

#[derive(Debug, Clone)]
pub enum AdbEvent {
    DeviceConnected(DeviceInfo),
    DeviceDisconnected(String),
    DeviceStatusChanged(String, DeviceStatus),
    HeartbeatUpdate(String, DateTime<Utc>),
    Error(String, AdbError),
}

/// ADB设备管理器 - 使用命令行方式
pub struct AdbManager {
    adb_path: String,
    devices: Arc<Mutex<HashMap<String, DeviceInfo>>>,
    event_sender: broadcast::Sender<AdbEvent>,
    heartbeat_interval: tokio::time::Duration,
}

impl AdbManager {
    /// 创建新的ADB管理器实例
    pub async fn new() -> Result<Self, AdbError> {
        info!("Initializing ADB Manager with bundled platform-tools");
        
        // 使用绝对路径指向捆绑的ADB
        let bundled_adb = std::path::PathBuf::from("D:/workspace/rust2025/new_media/src-tauri/resources/platform-tools/adb.exe");
        
        let adb_path = if bundled_adb.exists() {
            info!("Using bundled ADB from resources directory");
            bundled_adb.to_string_lossy().to_string()
        } else {
            // 如果捆绑的ADB不存在，尝试相对路径
            if let Ok(mut exe_path) = std::env::current_exe() {
                exe_path.pop(); // 移除可执行文件名
                
                // 尝试多个可能的路径
                let possible_paths = vec![
                    exe_path.join("../src-tauri/resources/platform-tools/adb.exe"),
                    exe_path.join("resources/platform-tools/adb.exe"),
                    exe_path.join("../resources/platform-tools/adb.exe"),
                ];
                
                let mut found_path = None;
                for path in possible_paths {
                    if path.exists() {
                        found_path = Some(path.to_string_lossy().to_string());
                        break;
                    }
                }
                
                if let Some(path) = found_path {
                    info!("Found ADB at: {}", path);
                    path
                } else {
                    // 最后尝试从PATH中查找
                    match which("adb") {
                        Ok(path) => {
                            info!("Using system ADB from PATH");
                            path.to_string_lossy().to_string()
                        },
                        Err(_) => {
                            error!("ADB not found in bundled resources or PATH");
                            return Err(AdbError::AdbNotFound);
                        }
                    }
                }
            } else {
                // 无法获取可执行文件路径，尝试从PATH中查找
                match which("adb") {
                    Ok(path) => path.to_string_lossy().to_string(),
                    Err(_) => {
                        error!("ADB not found");
                        return Err(AdbError::AdbNotFound);
                    }
                }
            }
        };

        info!("Using ADB at: {}", adb_path);

        // 启动ADB服务器
        if let Err(e) = Self::start_adb_server(&adb_path).await {
            warn!("Failed to start ADB server: {}, will continue anyway", e);
        }

        let (event_sender, _) = broadcast::channel(100);
        
        Ok(AdbManager {
            adb_path,
            devices: Arc::new(Mutex::new(HashMap::new())),
            event_sender,
            heartbeat_interval: tokio::time::Duration::from_secs(30),
        })
    }

    /// 启动ADB服务器
    async fn start_adb_server(adb_path: &str) -> Result<(), AdbError> {
        info!("Starting ADB server");
        
        let output = TokioCommand::new(adb_path)
            .arg("start-server")
            .output()
            .await?;

        if output.status.success() {
            info!("ADB server started successfully");
            Ok(())
        } else {
            let error_msg = String::from_utf8_lossy(&output.stderr);
            Err(AdbError::ServerNotRunning(format!("Failed to start ADB server: {}", error_msg)))
        }
    }

    /// 扫描所有可用设备
    pub async fn scan_devices(&self) -> Result<Vec<DeviceInfo>, AdbError> {
        debug!("Scanning for ADB devices using command line");
        
        let output = TokioCommand::new(&self.adb_path)
            .arg("devices")
            .arg("-l")
            .output()
            .await?;

        if !output.status.success() {
            let error_msg = String::from_utf8_lossy(&output.stderr);
            return Err(AdbError::CommandFailed(format!("ADB devices command failed: {}", error_msg)));
        }

        let devices_output = String::from_utf8_lossy(&output.stdout);
        let mut device_infos = Vec::new();
        let mut devices_map = self.devices.lock().await;
        
        for line in devices_output.lines().skip(1) {
            if line.trim().is_empty() || line.starts_with("*") {
                continue;
            }
            
            let parts: Vec<&str> = line.split_whitespace().collect();
            if parts.len() >= 2 {
                let serial = parts[0];
                let state = parts[1];
                
                if state == "device" {
                    match self.create_device_info(serial, state).await {
                        Ok(device_info) => {
                            devices_map.insert(device_info.id.clone(), device_info.clone());
                            device_infos.push(device_info);
                        }
                        Err(e) => {
                            warn!("Failed to create device info for {}: {}", serial, e);
                        }
                    }
                }
            }
        }
        
        info!("Found {} ADB devices", device_infos.len());
        Ok(device_infos)
    }

    /// 创建设备信息
    async fn create_device_info(&self, serial: &str, state: &str) -> Result<DeviceInfo, AdbError> {
        let device_id = Uuid::new_v4().to_string();
        
        let device_status = match state {
            "device" => DeviceStatus::Online,
            "offline" => DeviceStatus::Offline,
            _ => DeviceStatus::Offline,
        };

        let connection_type = if serial.contains(':') {
            let parts: Vec<&str> = serial.split(':').collect();
            ConnectionType::Network {
                ip: parts[0].to_string(),
                port: parts.get(1).unwrap_or(&"5555").parse().unwrap_or(5555),
            }
        } else {
            ConnectionType::Usb
        };

        let system_info = self.get_system_info(serial).await.ok();
        let device_name = system_info.as_ref()
            .map(|info| info.model.clone())
            .unwrap_or_else(|| serial.to_string());

        Ok(DeviceInfo {
            id: device_id,
            name: device_name,
            platform: Platform::Android,
            connection_type,
            status: device_status,
            system_info,
            last_heartbeat: Some(Utc::now()),
        })
    }

    /// 连接到指定设备（支持IP连接）
    pub async fn connect_device(&self, device_id: &str) -> Result<(), AdbError> {
        info!("Connecting to device: {}", device_id);
        
        // 检查是否是IP地址格式（支持 IP:PORT 或仅 IP）
        if device_id.contains('.') || device_id.contains(':') {
            // 这是一个网络地址，使用adb connect命令
            let address = if device_id.contains(':') {
                device_id.to_string()
            } else {
                format!("{}:5555", device_id) // 默认端口5555
            };
            
            info!("Connecting to network device: {}", address);
            
            let output = TokioCommand::new(&self.adb_path)
                .arg("connect")
                .arg(&address)
                .output()
                .await?;
            
            let result = String::from_utf8_lossy(&output.stdout);
            
            if output.status.success() && (result.contains("connected") || result.contains("already connected")) {
                info!("Successfully connected to: {}", address);
                
                // 扫描设备以更新列表
                tokio::time::sleep(tokio::time::Duration::from_millis(500)).await;
                self.scan_devices().await?;
                
                Ok(())
            } else {
                let error_msg = if !output.stderr.is_empty() {
                    String::from_utf8_lossy(&output.stderr).to_string()
                } else {
                    result.to_string()
                };
                Err(AdbError::Connection(format!("Failed to connect to {}: {}", address, error_msg)))
            }
        } else {
            // 原有逻辑：更新已存在设备的状态
            let mut devices = self.devices.lock().await;
            if let Some(device) = devices.get_mut(device_id) {
                device.status = DeviceStatus::Online;
                device.last_heartbeat = Some(Utc::now());
                
                let _ = self.event_sender.send(AdbEvent::DeviceConnected(device.clone()));
                info!("Device connected successfully: {}", device_id);
                Ok(())
            } else {
                Err(AdbError::DeviceNotFound(device_id.to_string()))
            }
        }
    }

    /// 断开设备连接
    pub async fn disconnect_device(&self, device_id: &str) -> Result<(), AdbError> {
        info!("Disconnecting device: {}", device_id);
        
        // 检查是否是网络设备
        if device_id.contains('.') || device_id.contains(':') {
            let address = if device_id.contains(':') {
                device_id.to_string()
            } else {
                format!("{}:5555", device_id)
            };
            
            info!("Disconnecting network device: {}", address);
            
            let output = TokioCommand::new(&self.adb_path)
                .arg("disconnect")
                .arg(&address)
                .output()
                .await?;
            
            if output.status.success() {
                info!("Successfully disconnected from: {}", address);
                
                // 从设备列表中移除
                let mut devices = self.devices.lock().await;
                devices.retain(|_, device| {
                    if let ConnectionType::Network { ip, port } = &device.connection_type {
                        let device_addr = format!("{}:{}", ip, port);
                        device_addr != address
                    } else {
                        true
                    }
                });
                
                let _ = self.event_sender.send(AdbEvent::DeviceDisconnected(address));
                Ok(())
            } else {
                let error_msg = String::from_utf8_lossy(&output.stderr);
                Err(AdbError::CommandFailed(format!("Disconnect failed: {}", error_msg)))
            }
        } else {
            // 原有逻辑：更新设备状态
            let mut devices = self.devices.lock().await;
            if let Some(device) = devices.get_mut(device_id) {
                device.status = DeviceStatus::Offline;
                
                let _ = self.event_sender.send(AdbEvent::DeviceDisconnected(device_id.to_string()));
                info!("Device disconnected: {}", device_id);
                Ok(())
            } else {
                Err(AdbError::DeviceNotFound(device_id.to_string()))
            }
        }
    }

    /// 获取设备截图
    pub async fn take_screenshot(&self, device_id: &str) -> Result<Vec<u8>, AdbError> {
        info!("Taking screenshot for device: {}", device_id);
        
        let serial = self.get_device_serial(device_id).await?;
        
        let output = TokioCommand::new(&self.adb_path)
            .arg("-s")
            .arg(serial)
            .arg("exec-out")
            .arg("screencap")
            .arg("-p")
            .output()
            .await?;

        if output.status.success() {
            info!("Screenshot captured for device: {}", device_id);
            Ok(output.stdout)
        } else {
            let error_msg = String::from_utf8_lossy(&output.stderr);
            Err(AdbError::CommandFailed(format!("Screenshot failed: {}", error_msg)))
        }
    }

    /// 获取设备性能指标
    pub async fn get_performance_metrics(&self, device_id: &str) -> Result<PerformanceMetrics, AdbError> {
        debug!("Getting performance metrics for device: {}", device_id);
        
        let serial = self.get_device_serial(device_id).await?;
        
        // 获取CPU使用率 (简化实现)
        let cpu_usage = self.get_cpu_usage(&serial).await.unwrap_or(0.0);
        
        // 获取内存使用情况
        let memory_usage = self.get_memory_usage(&serial).await.unwrap_or(0.0);
        
        // 获取电池电量
        let battery_level = self.get_battery_level(&serial).await.ok();
        
        Ok(PerformanceMetrics {
            cpu_usage,
            memory_usage,
            battery_level,
            temperature: None,
            network_speed: None,
        })
    }

    /// 获取设备系统信息
    async fn get_system_info(&self, serial: &str) -> Result<SystemInfo, AdbError> {
        let model = self.get_property(serial, "ro.product.model").await
            .unwrap_or_else(|_| "Unknown".to_string());
        
        let version = self.get_property(serial, "ro.build.version.release").await
            .unwrap_or_else(|_| "Unknown".to_string());
        
        let resolution = self.get_screen_resolution(serial).await
            .unwrap_or_else(|_| "Unknown".to_string());
        
        let memory = self.get_memory_info(serial).await
            .unwrap_or_else(|_| "Unknown".to_string());
        
        let storage = self.get_storage_info(serial).await
            .unwrap_or_else(|_| "Unknown".to_string());
        
        let cpu = self.get_property(serial, "ro.product.cpu.abi").await
            .unwrap_or_else(|_| "Unknown".to_string());

        Ok(SystemInfo {
            model,
            version,
            resolution,
            memory,
            storage,
            cpu,
            network: None,
        })
    }

    /// 执行shell命令
    async fn shell_command(&self, serial: &str, command: &str) -> Result<String, AdbError> {
        let output = TokioCommand::new(&self.adb_path)
            .arg("-s")
            .arg(serial)
            .arg("shell")
            .arg(command)
            .output()
            .await?;

        if output.status.success() {
            Ok(String::from_utf8_lossy(&output.stdout).trim().to_string())
        } else {
            let error_msg = String::from_utf8_lossy(&output.stderr);
            Err(AdbError::CommandFailed(format!("Shell command failed: {}", error_msg)))
        }
    }

    /// 获取设备属性
    async fn get_property(&self, serial: &str, property: &str) -> Result<String, AdbError> {
        let command = format!("getprop {}", property);
        self.shell_command(serial, &command).await
    }

    /// 获取屏幕分辨率
    async fn get_screen_resolution(&self, serial: &str) -> Result<String, AdbError> {
        let output = self.shell_command(serial, "wm size").await?;
        
        if let Some(line) = output.lines().find(|line| line.contains("Physical size:")) {
            if let Some(size) = line.split(':').nth(1) {
                return Ok(size.trim().to_string());
            }
        }
        
        Err(AdbError::ParseError("Cannot parse screen resolution".to_string()))
    }

    /// 获取内存信息
    async fn get_memory_info(&self, serial: &str) -> Result<String, AdbError> {
        let output = self.shell_command(serial, "cat /proc/meminfo | head -1").await?;
        
        if let Some(line) = output.lines().next() {
            if let Some(mem_str) = line.split_whitespace().nth(1) {
                if let Ok(mem_kb) = mem_str.parse::<u64>() {
                    let mem_mb = mem_kb / 1024;
                    return Ok(format!("{} MB", mem_mb));
                }
            }
        }
        
        Ok("Unknown".to_string())
    }

    /// 获取存储信息
    async fn get_storage_info(&self, serial: &str) -> Result<String, AdbError> {
        let output = self.shell_command(serial, "df /data | tail -1").await?;
        
        if let Some(line) = output.lines().next() {
            let parts: Vec<&str> = line.split_whitespace().collect();
            if parts.len() >= 2 {
                if let Ok(total_kb) = parts[1].parse::<u64>() {
                    let total_gb = total_kb / 1024 / 1024;
                    return Ok(format!("{} GB", total_gb));
                }
            }
        }
        
        Ok("Unknown".to_string())
    }

    /// 获取CPU使用率
    async fn get_cpu_usage(&self, _serial: &str) -> Result<f32, AdbError> {
        // 简化实现 - 返回模拟数据
        // TODO: 实现真实的CPU监控
        Ok(25.0)
    }

    /// 获取内存使用率
    async fn get_memory_usage(&self, _serial: &str) -> Result<f32, AdbError> {
        // 简化实现 - 返回模拟数据
        // TODO: 实现真实的内存监控
        Ok(60.0)
    }

    /// 获取电池电量
    async fn get_battery_level(&self, serial: &str) -> Result<f32, AdbError> {
        let output = self.shell_command(serial, "dumpsys battery | grep level").await?;
        
        if let Some(line) = output.lines().find(|line| line.contains("level:")) {
            if let Some(level_str) = line.split(':').nth(1) {
                if let Ok(level) = level_str.trim().parse::<f32>() {
                    return Ok(level);
                }
            }
        }
        
        Err(AdbError::ParseError("Cannot parse battery level".to_string()))
    }

    /// 根据设备ID获取串口号
    async fn get_device_serial(&self, device_id: &str) -> Result<String, AdbError> {
        let devices = self.devices.lock().await;
        if let Some(_device) = devices.get(device_id) {
            // TODO: 实现设备ID到串口号的映射
            // 目前返回第一个可用设备的串口号
            Ok("emulator-5554".to_string()) // 临时实现
        } else {
            Err(AdbError::DeviceNotFound(device_id.to_string()))
        }
    }

    /// 启动心跳监控
    pub async fn start_heartbeat_monitor(&self) {
        info!("Starting heartbeat monitor");
        
        let devices = self.devices.clone();
        let event_sender = self.event_sender.clone();
        let interval = self.heartbeat_interval;
        
        tokio::spawn(async move {
            let mut interval_timer = tokio::time::interval(interval);
            
            loop {
                interval_timer.tick().await;
                
                let device_ids: Vec<String> = {
                    let devices_guard = devices.lock().await;
                    devices_guard.keys().cloned().collect()
                };
                
                for device_id in device_ids {
                    if let Err(e) = Self::check_device_heartbeat(&device_id, &devices, &event_sender).await {
                        warn!("Heartbeat check failed for device {}: {}", device_id, e);
                    }
                }
            }
        });
    }

    /// 检查设备心跳
    async fn check_device_heartbeat(
        device_id: &str,
        devices: &Arc<Mutex<HashMap<String, DeviceInfo>>>,
        event_sender: &broadcast::Sender<AdbEvent>,
    ) -> Result<(), AdbError> {
        let now = Utc::now();
        let mut devices_guard = devices.lock().await;
        
        if let Some(device) = devices_guard.get_mut(device_id) {
            if let Some(last_heartbeat) = device.last_heartbeat {
                let duration = now.signed_duration_since(last_heartbeat);
                
                if duration.num_seconds() > 60 {
                    device.status = DeviceStatus::Offline;
                    let _ = event_sender.send(AdbEvent::DeviceStatusChanged(
                        device_id.to_string(),
                        DeviceStatus::Offline,
                    ));
                    warn!("Device {} marked as offline due to heartbeat timeout", device_id);
                }
            }
            
            device.last_heartbeat = Some(now);
            let _ = event_sender.send(AdbEvent::HeartbeatUpdate(device_id.to_string(), now));
        }
        
        Ok(())
    }

    /// 订阅设备事件
    pub fn subscribe_events(&self) -> broadcast::Receiver<AdbEvent> {
        self.event_sender.subscribe()
    }

    /// 获取所有设备
    pub async fn get_all_devices(&self) -> Result<Vec<DeviceInfo>, AdbError> {
        let devices = self.devices.lock().await;
        Ok(devices.values().cloned().collect())
    }
}